package com.qsd.TeacherSystem.Service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qsd.TeacherSystem.Service.PaperService;
import com.qsd.TeacherSystem.dao.PaperDao;
import com.qsd.common.enums.ResultStatus;
import com.qsd.common.po.*;
import com.qsd.common.pojo.PaperEntity;
import com.qsd.common.util.JdbcUtil;
import com.qsd.common.util.PageUtil;
import com.qsd.common.vo.PageVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Date;
import java.util.*;


@Slf4j
@Service
public class PaperServiceImpl implements PaperService {

    @Resource
    private PaperDao paperDao;


    @Override
    public List<PaperEntity> paperList2(Paper paper, PageUtil page) {


        LambdaQueryWrapper<PaperEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(paper.getName()), PaperEntity::getName, paper.getName())
                .notLike(PaperEntity::getName,"_tk");
        Page<PaperEntity> paperEntityPage = paperDao.selectPage(new Page<>(page.getPage(), page.getLimit()), queryWrapper);
        page.setCount((int) paperEntityPage.getTotal());
        return paperEntityPage.getRecords();
    }

    @Override
    public PageVo<Paper> all(Integer id) {
        List<Paper> papers = paperDao.queryByCourseId(id);
        return new PageVo<>(ResultStatus.SUCCESS, papers.size(), papers);
    }

    @Override
    public PageVo<Paper> papers(int page, int limit, String username) {
        List<Paper> papers = paperDao.queryAllByUsername(username);
        return JdbcUtil.PageUtil(page, limit, papers);
    }

    @Override
    public PageVo<Paper> papers2(int page, int limit, String username) {
        List<Paper> papers = paperDao.queryAllByUsername2(username);
        return JdbcUtil.PageUtil(page, limit, papers);
    }

    @Override
    public ResultStatus add(Paper paper, String username) {
        //create_time
        Date createTime = new Date(System.currentTimeMillis());
        //setting
        paper.setTeacherUsername(username);
        paper.setCreateTime(createTime);
        //insert
//		int savePaper = paperDao.save(paper);

        PaperEntity paperEntity = BeanUtil.copyProperties(paper, PaperEntity.class);
        int savePaper = paperDao.insert(paperEntity);
        if (savePaper > 0) {
            return ResultStatus.SUCCESS;
        }

        return ResultStatus.SYSTEM_ERROR;
    }


    @Override
    public ResultStatus update(Paper paper) {
        System.err.println(paper.getName());
        int update = paperDao.update(paper);
        if (update > 0) {
            return ResultStatus.SUCCESS;
        }
        return ResultStatus.SYSTEM_ERROR;
    }

    @Override
    public Paper queryPaperById(Integer id) {
        int grade = 0;
        Paper paper = paperDao.queryById(id);
        List<OneChoice> oneChoices = paperDao.queryOneChoicesByPaperId(id);

        for (OneChoice oneChoice : oneChoices) {
            grade += oneChoice.getScore();
        }
        List<MultipleChoice> multipleChoices = paperDao.queryMultipleChoicesByPaperId(id);
        for (MultipleChoice multipleChoice : multipleChoices) {
            grade += multipleChoice.getScore();
        }
        List<Judgment> judgments = paperDao.queryJudgmentsByPaperId(id);
        for (Judgment judgment : judgments) {
            grade += judgment.getScore();
        }
        List<FullInTheBlank> fullInTheBlanks = paperDao.queryFullInTheBlanksByPaperId(id);
        for (FullInTheBlank fullInTheBlank : fullInTheBlanks) {
            grade += fullInTheBlank.getScore();
        }
        List<Discussion> discussions = paperDao.queryDiscussionsByPaperId(id);
        for (Discussion discussion : discussions) {
            grade += discussion.getScore();
        }


        paper.setOneChoices(oneChoices);
        paper.setMultipleChoices(multipleChoices);
        paper.setJudgments(judgments);
        paper.setFullInTheBlanks(fullInTheBlanks);
        paper.setDiscussions(discussions);
        paper.setGrade(grade);
        return paper;
    }


    @Override
    public Paper queryPaperById2(Integer id) {

        log.info("随机组卷");
        Paper paper = paperDao.queryById(id);
        List<OneChoice> oneChoices = paperDao.queryOneChoicesByPaperId(id);
        //1:获取重组后的单选列表
        Map<String, List<OneChoice>> oneChoice = this.getRandomMap(id, oneChoices, "oneChoice");
        List<OneChoice> oneLs = oneChoice.get("oneChoice");

        List<MultipleChoice> multipleChoices = paperDao.queryMultipleChoicesByPaperId(id);
        //2:获取重组后的多选题列表
        Map<String, List<MultipleChoice>> mulChoice = this.getRandomMap(id, multipleChoices, "multipleChoice");
        List<MultipleChoice> mulLs = mulChoice.get("multipleChoice");

        List<Judgment> judgments = paperDao.queryJudgmentsByPaperId(id);
        //3:获取重组后的判断题
        Map<String, List<Judgment>> judgmentsMp = this.getRandomMap(id, judgments, "judgment");
        List<Judgment> judLs = judgmentsMp.get("judgment");


        List<FullInTheBlank> fullInTheBlanks = paperDao.queryFullInTheBlanksByPaperId(id);
        //3:获取重组后的判断题
        Map<String, List<FullInTheBlank>> fullMp = this.getRandomMap(id, fullInTheBlanks, "fullInTheBlank");
        List<FullInTheBlank> fulLs = fullMp.get("fullInTheBlank");

        List<Discussion> discussions = paperDao.queryDiscussionsByPaperId(id);
        //3:获取重组后的判断题
        Map<String, List<Discussion>> disMp = this.getRandomMap(id, discussions, "discussion");
        List<Discussion> disLs = disMp.get("discussion");


        paper.setOneChoices(oneLs);
        paper.setMultipleChoices(mulLs);
        paper.setJudgments(judLs);
        paper.setFullInTheBlanks(fulLs);
        paper.setDiscussions(disLs);
        return paper;
    }


    private <T> Map<String, List<T>> getRandomMap(Integer id, List<T> ld, String type) {

        Map<String, List<T>> mp = new HashMap<>();
        if (StringUtils.equals("oneChoice", type)) {
            this.getOneChoiceMap(id, (List<OneChoice>) ld, mp);
        } else if (StringUtils.equals("multipleChoice", type)) {
            this.getMulChoiceMap(id, (List<MultipleChoice>) ld, mp);
        } else if (StringUtils.equals("judgment", type)) {
            this.getJudMap(id, (List<Judgment>) ld, mp);
        } else if (StringUtils.equals("fullInTheBlank", type)) {
            this.getFullMap(id, (List<FullInTheBlank>) ld, mp);
        } else if (StringUtils.equals("discussion", type)) {
            this.getDisMap(id, (List<Discussion>) ld, mp);
        }
        return mp;
    }

    private <T> void getDisMap(Integer id, List<Discussion> oneChoices, Map<String, List<T>> mp) {
        List<Discussion> ll = new ArrayList<>();
        long degree_1 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 1)
                .count();
        findDisFromDao(id, ll, degree_1, "1");
        long degree_2 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 2)
                .count();
        findDisFromDao(id, ll, degree_2, "2");
        long degree_3 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 3)
                .count();
        findDisFromDao(id, ll, degree_3, "3");
        long degree_4 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 4)
                .count();
        findDisFromDao(id, ll, degree_4, "4");
        long degree_5 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 5)
                .count();
        findDisFromDao(id, ll, degree_5, "5");
        mp.put("discussion", (List<T>) ll);
        
    }

    private void findDisFromDao(Integer id, List<Discussion> ll, long degreeNum, String s) {

        if (degreeNum > 0) {
            //随机查询出难度为s的
            List<Discussion> ones = paperDao.findDisFromDaoByRandom(id, s);
            for (int i = 0; i < degreeNum; i++) {
                Random random = new Random();
                int n = random.nextInt(ones.size());
                Discussion discussion = ones.get(n);
                ll.add(discussion);
            }
        }
    }

    private <T> void getFullMap(Integer id, List<FullInTheBlank> oneChoices, Map<String, List<T>> mp) {

        List<FullInTheBlank> ll = new ArrayList<>();
        long degree_1 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 1)
                .count();
        findFullFromDao(id, ll, degree_1, "1");
        long degree_2 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 2)
                .count();
        findFullFromDao(id, ll, degree_2, "2");
        long degree_3 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 3)
                .count();
        findFullFromDao(id, ll, degree_3, "3");
        long degree_4 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 4)
                .count();
        findFullFromDao(id, ll, degree_4, "4");
        long degree_5 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 5)
                .count();
        findFullFromDao(id, ll, degree_5, "5");
        mp.put("fullInTheBlank", (List<T>) ll);
    }

    private void findFullFromDao(Integer id, List<FullInTheBlank> ll, long degreeNum, String s) {

        if (degreeNum > 0) {
            //随机查询出难度为s的
            List<FullInTheBlank> ones = paperDao.findFullFromDaoByRandom(id, s);
            for (int i = 0; i < degreeNum; i++) {
                Random random = new Random();
                int n = random.nextInt(ones.size());
                FullInTheBlank discussion = ones.get(n);
                ll.add(discussion);
            }
        }
    }

    private <T> void getJudMap(Integer id, List<Judgment> oneChoices, Map<String, List<T>> mp) {

        List<Judgment> ll = new ArrayList<>();
        long degree_1 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 1)
                .count();
        findJudFromDao(id, ll, degree_1, "1");
        long degree_2 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 2)
                .count();
        findJudFromDao(id, ll, degree_2, "2");
        long degree_3 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 3)
                .count();
        findJudFromDao(id, ll, degree_3, "3");
        long degree_4 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 4)
                .count();
        findJudFromDao(id, ll, degree_4, "4");
        long degree_5 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 5)
                .count();
        findJudFromDao(id, ll, degree_5, "5");
        mp.put("judgment", (List<T>) ll);

        
    }

    private void findJudFromDao(Integer id, List<Judgment> ll, long degreeNum, String s) {
        if (degreeNum > 0) {
            //随机查询出难度为s的
            List<Judgment> ones = paperDao.findJudFromDaoByRandom(id, s);
            for (int i = 0; i < degreeNum; i++) {
                Random random = new Random();
                int n = random.nextInt(ones.size());
                Judgment oneChoice = ones.get(n);
                ll.add(oneChoice);
            }
        }
    }

    private <T> void getMulChoiceMap(Integer id, List<MultipleChoice> oneChoices, Map<String, List<T>> mp) {

        List<MultipleChoice> ll = new ArrayList<>();
        long degree_1 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 1)
                .count();
        findMulChoiceFromDao(id, ll, degree_1, "1");
        long degree_2 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 2)
                .count();
        findMulChoiceFromDao(id, ll, degree_2, "2");
        long degree_3 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 3)
                .count();
        findMulChoiceFromDao(id, ll, degree_3, "3");
        long degree_4 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 4)
                .count();
        findMulChoiceFromDao(id, ll, degree_4, "4");
        long degree_5 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 5)
                .count();
        findMulChoiceFromDao(id, ll, degree_5, "5");
        mp.put("multipleChoice", (List<T>) ll);

    }

    private void findMulChoiceFromDao(Integer id, List<MultipleChoice> ll, long degreeNum, String s) {
        if (degreeNum > 0) {
            //随机查询出难度为s的
            List<MultipleChoice> ones = paperDao.findMulChoiceByRandom(id, s);
            for (int i = 0; i < degreeNum; i++) {
                Random random = new Random();
                int n = random.nextInt(ones.size());
                MultipleChoice oneChoice = ones.get(n);
                ll.add(oneChoice);
            }
        }
    }

    /**
     * 重组单选
     *
     * @param id
     * @param oneChoices
     * @param mp
     * @param <T>
     */
    private <T> void getOneChoiceMap(Integer id, List<OneChoice> oneChoices, Map<String, List<T>> mp) {
        List<OneChoice> ll = new ArrayList<>();
        long degree_1 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 1)
                .count();
        findChoiceFromDao(id, ll, degree_1, "1");
        long degree_2 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 2)
                .count();
        findChoiceFromDao(id, ll, degree_2, "2");
        long degree_3 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 3)
                .count();
        findChoiceFromDao(id, ll, degree_3, "3");
        long degree_4 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 4)
                .count();
        findChoiceFromDao(id, ll, degree_4, "4");
        long degree_5 = oneChoices.stream()
                .filter(dto -> dto.getDegree() == 5)
                .count();
        findChoiceFromDao(id, ll, degree_5, "5");
        mp.put("oneChoice", (List<T>) ll);
    }


    private void findChoiceFromDao(Integer id, List<OneChoice> ll, long degreeNum, String s) {
        if (degreeNum > 0) {
            //随机查询出难度为s的
            List<OneChoice> ones = paperDao.findOneChoiceByRandom(id, s);
            for (int i = 0; i < degreeNum; i++) {
                Random random = new Random();
                int n = random.nextInt(ones.size());
                OneChoice oneChoice = ones.get(n);
                ll.add(oneChoice);
            }
        }
    }

    @Override
    public ResultStatus delete(String type, Integer id) {
        String name = "";
        //type:表名
        switch (type) {
            case "oneChoice":
                name = "one_choice";
                break;
            case "multipleChoice":
                name = "multiple_choice";
                break;
            case "judgment":
                name = "judgment";
                break;
            case "fullInTheBlank":
                name = "full_in_the_blank";
                break;
            case "discussion":
                name = "discussion";
                break;
            default:
                return ResultStatus.SYSTEM_ERROR;
        }
        int deleteByName = paperDao.deleteByName(name, id);
        if (deleteByName > 0) {
            return ResultStatus.SUCCESS;
        }
        return ResultStatus.SYSTEM_ERROR;
    }

    @Override
    public ResultStatus deletePage(Integer id) {

        try {
            paperDao.deleteByPageId("one_choice", id);
            paperDao.deleteByPageId("multiple_choice", id);
            paperDao.deleteByPageId("judgment", id);
            paperDao.deleteByPageId("full_in_the_blank", id);
            paperDao.deleteByPageId("one_choice", id);
            paperDao.deleteByPageId("discussion", id);
            paperDao.deleteByName("paper", id);
        } catch (Exception e) {
            log.error("删除试卷失败", e);
            return ResultStatus.SYSTEM_ERROR;
        }
        return ResultStatus.SUCCESS;
    }

    @Override
    public ResultStatus addOneChoice(OneChoice oneChoice) {
        int addOneChoice = paperDao.addOneChoice(oneChoice);
        if (addOneChoice > 0) {
            return ResultStatus.SUCCESS;
        }
        return ResultStatus.SYSTEM_ERROR;
    }

    @Override
    public ResultStatus addMultipleChoice(MultipleChoice multipleChoice) {
        int addMultipleChoice = paperDao.addMultipleChoice(multipleChoice);
        if (addMultipleChoice > 0) {
            return ResultStatus.SUCCESS;
        }
        return ResultStatus.SYSTEM_ERROR;
    }

    @Override
    public ResultStatus addJudgment(Judgment judgment) {
        int addJudgment = paperDao.addJudgment(judgment);
        if (addJudgment > 0) {
            return ResultStatus.SUCCESS;
        }
        return ResultStatus.SYSTEM_ERROR;
    }

    @Override
    public ResultStatus addFullInTheBlank(FullInTheBlank fullInTheBlank) {
        int addFullInTheBlank = paperDao.addFullInTheBlank(fullInTheBlank);
        if (addFullInTheBlank > 0) {
            return ResultStatus.SUCCESS;
        }
        return ResultStatus.SYSTEM_ERROR;
    }

    @Override
    public ResultStatus addDiscussion(Discussion discussion) {
        int addDiscussion = paperDao.addDiscussion(discussion);
        if (addDiscussion > 0) {
            return ResultStatus.SUCCESS;
        }
        return ResultStatus.SYSTEM_ERROR;
    }

}
